package com.jinke.api.modules.third.shipBridge.service.impl;

import cn.hutool.core.util.BooleanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.common.util.CommonUtil;
import com.jinke.api.common.util.Global;
import com.jinke.api.modules.app.enums.BalanceLogType;
import com.jinke.api.modules.app.enums.OrderStatus;
import com.jinke.api.modules.app.enums.OrderType;
import com.jinke.api.modules.app.enums.ValidateStatus;
import com.jinke.api.modules.app.model.Order;
import com.jinke.api.modules.app.model.OrderParcel;
import com.jinke.api.modules.app.response.CreateLabel2Response;
import com.jinke.api.modules.app.service.IUserOrderTaskService;
import com.jinke.api.modules.app.service.OrderParcelService;
import com.jinke.api.modules.app.service.OrderService;
import com.jinke.api.modules.app.service.UserRechargeService;
import com.jinke.api.modules.app.util.MathUtil;
import com.jinke.api.modules.app.util.OssUtil;
import com.jinke.api.modules.base.service.ThirdService;
import com.jinke.api.modules.third.easypost.model.request.GetLabelsRequest;
import com.jinke.api.modules.third.ezeeship.model.request.EstimateRateRequest;
import com.jinke.api.modules.third.ezeeship.model.response.CreateLabelResponse;
import com.jinke.api.modules.third.ezeeship.model.response.EstimateRateResponse;
import com.jinke.api.modules.third.ezeeship.service.EzeeShipService;
import com.jinke.api.modules.third.ezeeship.util.EzeeShipUtil;
import com.jinke.api.modules.third.shipBridge.service.ShipBridgeService;
import com.jinke.api.modules.third.shipBridge.util.ShipBridgeUtils;
import com.jinke.api.modules.ums.model.Channel;
import com.jinke.api.modules.ums.model.UmsAdmin;
import com.jinke.api.modules.ums.service.ChannelService;
import com.jinke.api.modules.ums.service.UmsAdminService;
import com.jinke.api.modules.ums.vo.UserChannelVO;
import com.jinke.api.security.util.ApiUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author huang
 * @data 2024-05-31
 */
@Slf4j
@Service
public class ShipBridgeServiceImpl implements ShipBridgeService {
    @Resource
    private ThirdService thirdService;
    @Resource
    private IUserOrderTaskService iUserOrderTaskService;
    @Resource
    private ChannelService channelService;
    @Resource
    private EzeeShipService ezeeShipService;
    @Resource
    private UmsAdminService umsAdminService;
    @Resource
    private ShipBridgeUtils shipBridgeUtils;
    @Resource
    private OssUtil ossUtil;
    @Resource
    private EzeeShipUtil ezeeShipUtil;
    @Resource
    private OrderService orderService;
    @Resource
    private OrderParcelService orderParcelService;
    @Resource
    private UserRechargeService userRechargeService;


    @Override
    public CommonResult estimateRate(EstimateRateRequest request) {
        Integer  userId = ApiUserUtil.getUserId();
        return estimateRate(request, userId);
    }

    @Override
    public CommonResult estimateRate(EstimateRateRequest request, Integer userId) {
        //查询渠道code
        Channel channel = channelService.getById(request.getChannelId());
        BigDecimal rate;
        //获取价格
        try {
            rate = getPrice(request, userId, channel.getChannelCode());
        } catch (Exception e) {
            return CommonResult.failed(e.getMessage());
        }
        if (rate.compareTo(new BigDecimal("0")) > 0) {
            EstimateRateResponse.Data newData = new EstimateRateResponse.Data();
            newData.setRate(rate);
            return CommonResult.success(newData);
        }
        //返回
        return CommonResult.failed("系统异常,请联系管理人员");
    }

    private BigDecimal getPrice(EstimateRateRequest request, Integer userId, String channelCode) {
        BigDecimal rateAmount = new BigDecimal("0");
        String result = shipBridgeUtils.getPrice(request, channelCode);
        /*String result = "{\n" +
                "    \"account_balance\": 20.0,\n" +
                "    \"currency\": \"USD\",\n" +
                "    \"rate\": {\n" +
                "        \"total\": 4.0,\n" +
                "        \"shipment\": 4.0,\n" +
                "        \"other\": 0,\n" +
                "        \"other_detail\": [\n" +
                "            \"fixed rate\"\n" +
                "        ]\n" +
                "    },\n" +
                "    \"service\": \"ups_ground_ep\",\n" +
                "    \"package\": \"package\",\n" +
                "    \"zone\": 8\n" +
                "}";*/
        if (StringUtils.isNotEmpty(result)) {
            //估价失败返回错误信息
            JSONObject jsonObject = JSON.parseObject(result);
            if (result.contains("text")) {
                throw new RuntimeException(jsonObject.getString("text"));
            }
            String rate = jsonObject.getJSONObject("rate").getString("total");
            rateAmount = thirdService.calcRate(userId, request.getUserChannelVO(), new BigDecimal(rate));
        }
        return rateAmount;
    }

    @Override
    public CommonResult createLabel(EstimateRateRequest request) {

        Integer userId = ApiUserUtil.getUserId();

        return createLabel(request, userId);
    }

    @Override
    public CommonResult createLabel(EstimateRateRequest request, Integer userId) {
        //判断数据是否缺失
        request.setOrderNO(StringUtils.isEmpty(request.getOrderNO()) ? CommonUtil.getOrderNo() : request.getOrderNO());
        UserChannelVO userChannelVO = request.getUserChannelVO();
        Channel channel = userChannelVO.getChannel();
        ezeeShipService.fillResidential(request, userId);
        //估价
        BigDecimal rate;
        try {
            rate = getPrice(request, userId, channel.getChannelCode());
        } catch (Exception e) {
            return CommonResult.failed(e.getMessage());
        }
        UmsAdmin umsAdmin = umsAdminService.getById(userId);
        if (rate.compareTo(new BigDecimal("0")) == 0 && ObjectUtils.isEmpty(umsAdmin)) {
            return CommonResult.failed("数据有误");
        }
        //判断余额是否充足
        BigDecimal totalAmount = umsAdmin.getBalance().add(umsAdmin.getCreditBalance());
        if (totalAmount.compareTo(rate) < 0) {
            return CommonResult.failed("Insufficient Balance");
        }
        //下单
        String result = shipBridgeUtils.createOrder(request, channel.getChannelCode());

        if (StringUtils.isNotEmpty(result)) {
            JSONObject jsonObject = JSON.parseObject(result);
            //第三方平台原始费用
            String originFee = jsonObject.getJSONObject("rate").getString("total");
            //溢价费用
            BigDecimal originFeeBd = new BigDecimal(originFee);

            BigDecimal afterRate = thirdService.calcRate(umsAdmin.getId(), request.getUserChannelVO(), originFeeBd);
            //上传pdf文件
            //运单号
            JSONArray trackingCode = jsonObject.getJSONArray("tracking_code");
            List<String> tackNumbers = new ArrayList<>(trackingCode.toJavaList(String.class));

            try {
                //扣减用户余额
                userRechargeService.decrTransfer(userId, afterRate, BalanceLogType.CONSUME, "寄件", request.getOrderNO(), null, null,null);

            }catch (Exception e) {
                //只能用物流号取消
                tackNumbers.forEach(
                        tackNumber -> shipBridgeUtils.cancel(tackNumber, request.getOrderNO())
                );
            }

            //pdfUrl
            String labelUrl = jsonObject.getString("label_url");
            String platformNoAndRequestId = CommonUtil.getOrderNo();

            GetLabelsRequest getLabelsRequest = new GetLabelsRequest();
            getLabelsRequest.setPlatformNo(platformNoAndRequestId);
            ossUtil.upload("pdf", platformNoAndRequestId + ".pdf", labelUrl);
            String newPdfUrl = Global.PRINT_LABEL_API + platformNoAndRequestId;



            //保存或者修改订单信息
            Order order = saveOrUpdateOrder(request, umsAdmin, originFeeBd, platformNoAndRequestId, newPdfUrl,afterRate);

            //定时任务表插入一条数据
            iUserOrderTaskService.saveByOrderId(order.getId());
            //修改包裹信息

            updateParcel(request.getParcels(), tackNumbers, order);

            //返回信息
            CreateLabelResponse.Data newCreateLabelResponseData = new CreateLabelResponse.Data();
            newCreateLabelResponseData.setRate(order.getRate());

            CreateLabel2Response.FeeDetail newFeeDetail = new CreateLabel2Response.FeeDetail();
            newFeeDetail.setBaseRate(order.getRate());
            newCreateLabelResponseData.setFeeDetail(newFeeDetail);

            newCreateLabelResponseData.setRate(order.getRate());
            newCreateLabelResponseData.setStatus(1);
            newCreateLabelResponseData.setCreateTime(LocalDateTime.now());
            newCreateLabelResponseData.setObjectId(platformNoAndRequestId);
            newCreateLabelResponseData.setPdfUrl(newPdfUrl);
            newCreateLabelResponseData.setTrackingNumber(tackNumbers);
            String pdfUrl = Global.PRINT_LABEL_API + platformNoAndRequestId;
            newCreateLabelResponseData.setLabelUrl(Collections.singletonList(pdfUrl));
            return CommonResult.success(newCreateLabelResponseData);
        }
        return CommonResult.failed("下单失败");
    }

    /**
     * 修改包裹信息
     *
     * @param parcels     下单参数包裹信息
     * @param tackNumbers 运单号
     * @param order       订单信息
     */
    private void updateParcel(List<EstimateRateRequest.Parcel> parcels, List<String> tackNumbers, Order order) {
        orderParcelService.remove(new LambdaQueryWrapper<OrderParcel>().eq(OrderParcel::getOrderId, order.getId()));
        List<OrderParcel> orderParcels = new ArrayList<>(tackNumbers.size());
        for (int i = 0; i < parcels.size(); i++) {
            EstimateRateRequest.Parcel parcel = parcels.get(i);
            for (int integer = 0; integer < parcel.getPackageNum(); integer++) {
                OrderParcel orderParcel = new OrderParcel();
                BeanUtils.copyProperties(parcel, orderParcel);
                orderParcels.add(orderParcel);
            }
        }
        for (int i = 0; i < orderParcels.size(); i++) {
            OrderParcel orderParcel = orderParcels.get(i);
            String tackNumber = tackNumbers.get(i);
            orderParcel.setOrderId(order.getId());
            orderParcel.setUserId(order.getUserId());
            orderParcel.setTrackingNumber(StringUtils.isNotBlank(tackNumber) ? tackNumber : tackNumbers.get(0));
        }
        orderParcelService.saveBatch(orderParcels);
    }

    /**
     * 保存或插入一条订单数据
     *
     * @param request                请求参数
     * @param umsAdmin               用户信息
     * @param                第三方原始费用
     * @param platformNoAndRequestId platformNo和RequestId
     * @param newPdfUrl              新pdfUrl
     * @param afterRate
     * @return 订单
     */
    private Order saveOrUpdateOrder(EstimateRateRequest request, UmsAdmin umsAdmin, BigDecimal originFeeBd, String platformNoAndRequestId, String newPdfUrl, BigDecimal afterRate) {
        Order order = new Order();
        BeanUtils.copyProperties(request, order);
        order.setId(request.getOrderId());
        order.setUserId(umsAdmin.getId());
        order.setErrMsg("");
        order.setOrderNo(request.getOrderNO());
        if (ObjectUtils.isNotEmpty(umsAdmin.getSellerId())) {
            order.setSellerId(umsAdmin.getSellerId());
        }


        order.setOriginFee(originFeeBd);
        order.setRate(afterRate);
        //计算保证金
        BigDecimal subEarnestBalance = MathUtil.formatBigDecimal(afterRate.multiply(umsAdmin.getEarnestRate()));
        order.setEarnest(subEarnestBalance);
        //这个第三方没有这些信息，放自己生成的
        order.setObjectId(platformNoAndRequestId);
        //这个第三方没有这些信息，放自己生成的
        order.setPlatformNo(platformNoAndRequestId);
        order.setPdfUrl(newPdfUrl);
        order.setStatus(OrderStatus.RECENT.getValue());
        order.setCreateTime(LocalDateTime.now());

        try {
            order.setReference(request.getExtra().getReference());
            order.setReference2(request.getExtra().getReference2());
        }catch (Exception e){
            log.error("设置reference出错了");
        }
        //更新地址信息
        order.setFromCity(request.getFrom().getCity());
        order.setFromEmail(request.getFrom().getEmail());
        order.setFromCompany(request.getFrom().getCompany());
        order.setFromPhone(request.getFrom().getPhone());
        order.setFromAddressLine2(request.getFrom().getAddressLine2());
        order.setFromAddressLine1(request.getFrom().getAddressLine1());
        order.setFromCountryCode(request.getFrom().getCountryCode());
        order.setFromZipCode(request.getFrom().getZipCode());
        order.setFromPersonName(request.getFrom().getPersonName());
        order.setFromStateCode(request.getFrom().getStateCode());

        EstimateRateRequest.Address requestTo = request.getTo();
        order.setToCity(requestTo.getCity());
        order.setToEmail(requestTo.getEmail());
        order.setToCompany(requestTo.getCompany());
        order.setToPhone(requestTo.getPhone());
        order.setToAddressLine2(requestTo.getAddressLine2());
        order.setToAddressLine1(requestTo.getAddressLine1());
        order.setToCountryCode(requestTo.getCountryCode());
        order.setToZipCode(requestTo.getZipCode());
        order.setToPersonName(requestTo.getPersonName());
        order.setToStateCode(requestTo.getStateCode());
        order.setOrderType(OrderType.API);
        if (BooleanUtil.isTrue(requestTo.getIsValid())) {
            order.setValidateStatus(ValidateStatus.defaultEnum(requestTo.getIsResidential()));
        } else {
            order.setValidateStatus(ValidateStatus.UN_VALIDATE);
        }
        orderService.saveOrUpdate(order);
        return order;
    }

    @Override
    public CommonResult getLabel(String objectId) {
        return null;
    }

    @Override
    public CommonResult getLabel(String objectId, Integer userId) {
        return null;
    }

    @Override
    public CommonResult cancelLabel(String objectId,String orderNo) {
        //查询对应订单是否存在
        Order order = orderService.lambdaQuery().eq(Order::getObjectId, objectId).eq(Order::getStatus,OrderStatus.RECENT).one();
        if (ObjectUtils.isNotEmpty(order)) {
            //查询包裹信息
            List<OrderParcel> orderParcelList = orderParcelService.lambdaQuery().eq(OrderParcel::getOrderId, order.getId()).list();
            if (CollectionUtils.isNotEmpty(orderParcelList)) {
                for (OrderParcel orderParcel : orderParcelList) {
                    //通过物流号取消
                    shipBridgeUtils.cancel(orderParcel.getTrackingNumber(),orderNo);
                }
            }
        }
        return CommonResult.failed("取消订单失败,未查询到对应订单信息");
    }

    @Override
    public CommonResult tracking(String trackingNumber) {
        return null;
    }

    @Override
    public CommonResult cancelInsurance(String insuranceId) {

        return CommonResult.success();
    }
}
